package br.unicamp.ic.lsd;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.perf4j.StopWatch;
import org.perf4j.commonslog.CommonsLogStopWatch;

import br.unicamp.ic.lsd.wscaa.WSCAAExecutor;
import br.unicamp.ic.lsd.wscaa.WSCAManager;
import br.unicamp.ic.lsd.wscaa.WebService;
import br.unicamp.ic.lsd.wscaa.api.ServiceRequest;
import br.unicamp.ic.lsd.wscaa.api.ServiceResponse;

/**
 * Hello world!
 * 
 */
// TODO: Mudar esquema da arvore xml informando no proprio no o handler?
// TODO: Quando nao encontrar o handler, lancar excecao HandlerNotFound?
public class Start {

    public final static String pathToXml = "/Users/renatomanzoni/Documents/workspace/mestrado/study-case-one/src/main/resources/resolution-rules.xml";

    public final static String wsdlWs2 = "http://localhost:8080/webservice-two/ServiceTwo?wsdl";
    public final static String wsdlWs3 = "http://localhost:8080/webservice-three/ServiceThree?wsdl";
    public final static String wsdlWs4 = "http://localhost:8080/webservice-four/ServiceFour?wsdl";
    
    private static Log logger = LogFactory.getLog(Start.class);

    private WSCAAExecutor wsca;

    // (H,I);(F,G);(H,I,J);(L,M) <-Handlers-> D,C,B,G
    public Start() throws InterruptedException {
	WSCAManager manager = new WSCAManager(pathToXml);

	ArrayList<WebService> wsList = new ArrayList<WebService>();
	// BusFactory bf = BusFactory.newInstance();
	wsList.add(new WebService(wsdlWs2, manager));
	wsList.add(new WebService(wsdlWs3, manager));
	wsList.add(new WebService(wsdlWs4, manager));
	//
	wsca = new WSCAAExecutor(wsList, manager);

	List<ServiceRequest> workParallelRequestFlowA = new ArrayList<ServiceRequest>();

	workParallelRequestFlowA.add(new ServiceRequest("methodOneWSTwo",
		new Object[] { new Integer(0) }));
	workParallelRequestFlowA.add(new ServiceRequest("methodOneWSFour",
		new Object[] { new Integer(0) }));

	List<ServiceRequest> workParallelRequestFlowB = new ArrayList<ServiceRequest>();

	workParallelRequestFlowB.add(new ServiceRequest("methodThreeWSTwo",
		new Object[] { new Integer(0) }));
	workParallelRequestFlowB.add(new ServiceRequest("methodTwoWSThree",
		new Object[] { new Integer(0) }));

	List<ServiceRequest> workParallelRequestFlowC = new ArrayList<ServiceRequest>();

	workParallelRequestFlowC.add(new ServiceRequest("methodOneWSTwo",
		new Object[] { new Integer(0) }));
	workParallelRequestFlowC.add(new ServiceRequest("methodOneWSFour",
		new Object[] { new Integer(0) }));
	workParallelRequestFlowC.add(new ServiceRequest("methodThreeWSThree",
		new Object[] { new Integer(0) }));

	List<ServiceRequest> workParallelRequestFlowD = new ArrayList<ServiceRequest>();

	workParallelRequestFlowD.add(new ServiceRequest("methodThreeWSFour",
		new Object[] { new Integer(0) }));
	workParallelRequestFlowD.add(new ServiceRequest("methodTwoWSFour",
		new Object[] { new Integer(0) }));

	while (true) {

	    final StopWatch stopWatch = new CommonsLogStopWatch();
	    
	    logger.info("---------------------------------");
	    logger.info("Invoking flow (H,I)");
	    List<ServiceResponse> servicesResponses = wsca
		    .executeWSCAA(workParallelRequestFlowA, 1000L);

	    for (Iterator<ServiceResponse> iterator = servicesResponses
		    .iterator(); iterator.hasNext();) {
		ServiceResponse serviceResponse = (ServiceResponse) iterator
			.next();
		logger.info(serviceResponse.hasException() ? null
			: serviceResponse.getReponses()[0]);
	    }
	    
	    logger.info("---------------------------------");
	    logger.info("Invoking flow (F,G)");
	    List<ServiceResponse> servicesResponsesB = wsca
		    .executeWSCAA(workParallelRequestFlowB, 1000L);

	    for (Iterator<ServiceResponse> iterator = servicesResponsesB
		    .iterator(); iterator.hasNext();) {
		ServiceResponse serviceResponse = (ServiceResponse) iterator
			.next();
		logger.info(serviceResponse.hasException() ? null
			: serviceResponse.getReponses()[0]);

	    }
	    logger.info("---------------------------------");
	    logger.info("Invoking flow (H,I,J)");
	    List<ServiceResponse> servicesResponsesC = wsca
		    .executeWSCAA(workParallelRequestFlowC, 1000L);

	    for (Iterator<ServiceResponse> iterator = servicesResponsesC
		    .iterator(); iterator.hasNext();) {
		ServiceResponse serviceResponse = (ServiceResponse) iterator
			.next();
		logger.info(serviceResponse.hasException() ? null
			: serviceResponse.getReponses()[0]);

	    }
	    logger.info("---------------------------------");
	    logger.info("Invoking flow (L,M)");
	    List<ServiceResponse> servicesResponsesD = wsca
		    .executeWSCAA(workParallelRequestFlowD, 1000L);

	    for (Iterator<ServiceResponse> iterator = servicesResponsesD
		    .iterator(); iterator.hasNext();) {
		ServiceResponse serviceResponse = (ServiceResponse) iterator
			.next();
		logger.info(serviceResponse.hasException() ? null
			: serviceResponse.getReponses()[0]);

	    }
	    stopWatch.stop("case-study-one.start");
	    Thread.sleep(5000);
	}

    }

    public static void main(String[] args) throws InterruptedException {
	logger.info("Iniciando Estudo de Caso 1:");
	new Start();
	logger.info("Fim?");
    }
}
